package com.yunhe.merchants.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.metadata.BaseExcelModel;
import com.yunhe.common.model.ResultObject;
import com.yunhe.common.model.authority.*;
import com.yunhe.common.model.ResultObject;
import com.yunhe.common.model.authority.Organization;
import com.yunhe.common.model.mybatis.PageResult;
import com.yunhe.common.model.office.Office;
import com.yunhe.common.util.RedisClient;
import com.yunhe.common.util.StringUtil;
import com.yunhe.merchants.client.AuthorityClient;
import com.yunhe.merchants.constant.MyProjectConsts;
import com.yunhe.merchants.domain.MyProject;
import com.yunhe.merchants.domain.ProcessStatus;
import com.yunhe.merchants.model.FilterCondition;
import com.yunhe.merchants.model.HistoryProjectUpload;
import com.yunhe.merchants.model.IntentionProjectUpload;
import com.yunhe.merchants.model.SuccessProjectUpload;
import com.yunhe.merchants.repository.*;
import com.yunhe.merchants.service.IMyProjectService;
import com.yunhe.merchants.util.MyHeaderUtil;
import com.yunhe.common.util.CollectionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: DongWenYu
 * @Date: 2021/5/7 21:18
 */
@Service
public class MyProjectServiceImpl implements IMyProjectService {

    private static final Logger logger = LoggerFactory.getLogger(MyProjectServiceImpl.class);

    protected static final int month = 1000 * 60 * 60 * 24 * 30;

    @Autowired
    MyProjectRepository myProjectRepository;

    @Autowired
    ProcessStatusRepository processStatusRepository;

    @Autowired
    AuthorityClient authorityClient;

    @Autowired
    RedisClient redisClient;

    @Autowired
    private MyHeaderUtil myHeaderUtil;

    @Override
    public PageResult selectByFilterCondition(FilterCondition filterCondition, List<String> status, Long userId, int page, int size) {
        Boolean find = autoWiredFilter(filterCondition, userId);
        if (find) {
            analysisText(filterCondition);
            PageHelper.startPage(page, size);
            List<MyProject> myProjects = myProjectRepository.selectByCondition(filterCondition, status);
            getOtherOffice(myProjects);
            for (MyProject myProject : myProjects) {
                if(MyProjectConsts.COMPANY_STATUS.Fail.value().equals(myProject.getCompanyStatus())){
                    ProcessStatus processStatus = processStatusRepository.getLastProcessWithOutFail(myProject.getId(),myProject.getCompanyStatus());
                    if(processStatus != null){
                        myProject.setFailedNode(processStatus.getStatus());
                    }else {
                        myProject.setFailedNode(MyProjectConsts.COMPANY_STATUS.Intention.value());
                    }
                }
            }
            PageInfo<MyProject> pageInfo = new PageInfo<>(myProjects);
            return new PageResult(page, size, (int) pageInfo.getTotal(), myProjects);
        } else {
            return null;
        }
    }

    private void getOtherOffice(List<MyProject> myProjects) {
        for (MyProject m : myProjects) {
            if (MyProjectConsts.BOOLEAN.Yes.value().equals(m.getExistOffice())) {
                String fieldValueString = m.getCompanyStatus();
                List<MyProject> myProjectList = selectOtherOfficeByProjectId(m.getId());
                if(CollectionUtil.isNotEmpty(myProjectList)){
                    for (MyProject myProject : myProjectList) {
                        myProject.setPrincipalTitle(getUserTitleById(myProject.getPrincipal()));
                        myProject.setCompanyStatusName(getCompanyStatusTitle(myProject.getCompanyStatus()));
                    }
                    m.setOtherOffice(myProjectList);
                }
            }
        }
    }

    private String getCompanyStatusTitle(String fieldValueString) {
        String enumItems = redisClient.get("ENUM_ITEM:"+"companyStatus");
        List<Map<String,Object>> maps = new ArrayList<>();
        maps = (List<Map<String, Object>>) JSON.parse(enumItems);
        if(!CollectionUtil.isEmpty(maps)){
            String finalFieldValueString = fieldValueString;
            List<Map<String, Object>> mapList = maps.stream().filter(map -> {
                return finalFieldValueString.equals(map.get("code"));
            }).collect(Collectors.toList());
            if(CollectionUtil.isEmpty(mapList)){
                for (Map<String, Object> map : maps) {
                    Object titleObj = map.get("title");
                    Object codeObj = map.get("code");
                    if(codeObj.equals(fieldValueString) || fieldValueString.contains(codeObj.toString())){
                        fieldValueString = fieldValueString.replace(codeObj.toString(),titleObj.toString());
                    }
                }
            }else {
                Object titleObj = mapList.get(0).get("title");
                Object codeObj = mapList.get(0).get("code");
                fieldValueString = fieldValueString.replace(codeObj.toString(),titleObj.toString());
            }
            return fieldValueString;
        }
        return null;
    }

    private String getUserTitleById(Long principal) {
        if (principal!= null) {
            String title = redisClient.get("UserName:" + principal);
            if (StringUtil.isEmpty(title)) {
                ResponseEntity<ResultObject<User>> resEntity = authorityClient.get(principal);
                if (resEntity != null) {
                    if (resEntity.getStatusCode().is2xxSuccessful()) {
                        ResultObject body = resEntity.getBody();
                        if (body != null) {
                            Object results = body.getResults();
                            if (results != null) {
                                User user = (User) results;
                                if (user != null) {
                                    redisClient.set("UserName:" + principal, JSON.toJSONString(user));
                                    return user.getTitle();
                                }
                            }
                        }
                    }
                }
            } else {
                User parse = JSON.toJavaObject((JSON) JSON.toJSON(JSON.parseObject(title)),User.class);
                return parse.getTitle();
            }
        }
        return null;
    }


    /**
     * 解析模糊查询的文本框，企业名称，客户姓名，电话
     *
     * @param filterCondition
     * @return void
     * @create 2021/5/11 15:13
     */
    protected void analysisText(FilterCondition filterCondition) {
        if (!StringUtil.isEmpty(filterCondition.getText())) {
            filterCondition.setTimeSort("0");
            filterCondition.setCustTel(filterCondition.getText());
            filterCondition.setCompanyName(filterCondition.getText());
            filterCondition.setCustName(filterCondition.getText());
        }
    }

    /**
     * 自动填充添加项目的负责人，负责部门，录入人，录入部门，创建更新时间
     *
     * @param myProject
     * @param userId
     * @return void
     * @create 2021/5/10 10:53
     */
    protected void autoWiredProjectByAdd(MyProject myProject, Long userId, Long stationId) {
        if (myProject.getPrincipal() == null) {
            //批量导入的情况
            myProject.setPrincipal(userId);
            myProject.setImportPerson(userId);
        }
        if (myProject.getEntryPerson() == null) {
            //批量导入的情况
            myProject.setEntryPerson(userId);
            myProject.setImportPerson(userId);
        }
        if (myProject.getResponsibleDept() == null) {
            myProject.setResponsibleDept(getOrgId(userId));
        }
        if (myProject.getEntryDept() == null) {
            myProject.setEntryDept(getOrgId(userId));
        }
        if (StringUtil.isEmpty(myProject.getCompanyStatus())){
            myProject.setCompanyStatus(MyProjectConsts.COMPANY_STATUS.Intention.value());
        }
        myProject.setCreateTime(new Date());
        myProject.setUpdateTime(new Date());
        myProject.setUpdater(userId);
        myProject.setStationId(stationId);
    }

    /**
     * 检测是否存在相同企业(撞车)
     *
     * @param myProject 导入的意向项目
     * @return void
     * @create 2021/5/10 10:48
     */
    protected void checkExistCompany(MyProject myProject) {
        if (!StringUtil.isEmpty(myProject.getCompanyName())
                && !StringUtil.isEmpty(myProject.getCustTel())) {
            List<MyProject> myProjects = myProjectRepository.selectByCNameAndCustTel(myProject.getCompanyName()
                    , myProject.getCustTel());
            if (CollectionUtil.isNotEmpty(myProjects)) {
                for (MyProject project : myProjects) {
                    if (!MyProjectConsts.BOOLEAN.Yes.value().equals(project.getExistCompany())) {
                        project.setExistCompany(MyProjectConsts.BOOLEAN.Yes.value());
                        myProjectRepository.update(project);
                    }
                }
                myProject.setExistCompany(MyProjectConsts.BOOLEAN.Yes.value());
            }
        }
    }

    /**
     * 根据项目id和状态值查当前状态
     *
     * @param id
     * @param status
     * @return com.yunhe.merchants.domain.ProcessStatus
     * @create 2021/5/11 15:16
     */
    @Override
    public ProcessStatus selectStatusById(Long id, String status) {
        MyProject myProject = myProjectRepository.selectById(id);
        if (myProject != null) {
            String companyStatus = myProject.getCompanyStatus();
            if (StringUtil.isEmpty(status)) {
                //为空表示最新状态
                return processStatusRepository.selectByProjectIdAndStatus(id, companyStatus);
            } else if (Integer.parseInt(status) > Integer.parseInt(companyStatus)) {
                //传入阶段在最新状态后面
                logger.info("还未进行到当前状态,id:{},status:{}" + id + status);
                return null;
            } else if (status.equals(companyStatus)) {
                //传入阶段在最新状态后面
                return processStatusRepository.selectByProjectIdAndStatus(id,companyStatus);
            } else {
                return processStatusRepository.selectByProjectIdAndStatus(id, status);
            }
        } else {
            logger.info("不存在id为{}的项目", id);
            return null;
        }
    }

    /**
     * 查询保护期限不为空的意向项目
     *
     * @return java.util.List<com.yunhe.merchants.domain.IntentionProject>
     * @create 2021/5/11 15:15
     */
    @Override
    public List<MyProject> selectProtectedRemind() {
        return myProjectRepository.selectProtectedRemind();
    }

    /**
     * 查找和当前id相同推荐厂房的list集合
     *
     * @param id
     * @return java.util.List<com.yunhe.merchants.domain.MyProject>
     * @create 2021/5/13 13:43
     */
    @Override
    public List<MyProject> selectOtherOfficeByProjectId(Long id) {
        MyProject myProject = myProjectRepository.selectById(id);
        if (myProject != null) {
            List<MyProject> myProjects = myProjectRepository.selectByOffice(myProject.getRecommendOffice());
            return myProjects.stream().filter(i -> !i.getId().equals(id)).collect(Collectors.toList());
        } else {
            logger.info("找不到该项目,id:{}", id);
            return null;
        }
    }

    @Override
    public List<MyProject> selectProtectedExpire() {
        return myProjectRepository.selectProtectedExpire();
    }

    @Override
    public List<MyProject> selectNoUpdate() {
        return myProjectRepository.selectNoUpdate();
    }

    @Override
    public void insert(MyProject myProject, Long userId, Long stationId) {
        autoWiredProjectByAdd(myProject, userId, stationId);
        checkExistCompany(myProject);
        myProjectRepository.insert(myProject);
    }

    @Override
    public MyProject selectById(Long id) {
        return myProjectRepository.selectById(id);
    }

    @Override
    public void update(MyProject myProject) {
        myProjectRepository.update(myProject);
    }

    @Override
    public void update(MyProject myProject, Long userId) {
        myProject.setUpdater(userId);
        myProject.setUpdateTime(new Date());
        myProjectRepository.update(myProject);
    }

    @Override
    public List<MyProject> export(String ids, FilterCondition filterCondition, List<String> status) {
        return getProjectsByIds(ids, filterCondition, status);
    }

    @Override
    public PageResult selectForLatestStatusList(FilterCondition filterCondition, int pageNum, int pageSize) throws ArgumentErrorException {
        PageMethod.startPage(pageNum, pageSize);
        Long userId = myHeaderUtil.getHeaderUser();
        if(userId == null){
            throw new ArgumentErrorException("登录信息已失效,请重新登录");
        }
        List<Organization> organizationList = subOrg(userId);
        List<Long> organizationIdList = organizationList.stream().map(Organization::getId).collect(Collectors.toList());
        filterCondition.setOrgIds(organizationIdList);
        List<MyProject> myProjectList = myProjectRepository.selectForLatestStatusList(filterCondition);
        getOtherOffice(myProjectList);
        for (MyProject myProject : myProjectList) {
            if(MyProjectConsts.COMPANY_STATUS.Fail.value().equals(myProject.getCompanyStatus())){
                ProcessStatus processStatus = processStatusRepository.getLastProcessWithOutFail(myProject.getId(),myProject.getCompanyStatus());
                if(processStatus != null){
                    myProject.setFailedNode(processStatus.getStatus());
                }else {
                    myProject.setFailedNode(MyProjectConsts.COMPANY_STATUS.Intention.value());
                }
            }
        }
        PageInfo<MyProject> pageInfo = new PageInfo<>(myProjectList);
        return new PageResult(pageNum, pageSize, (int) pageInfo.getTotal(), myProjectList);
    }

    @Override
    public void insertBatch(List<MyProject> myProjects) {
        for (MyProject myProject : myProjects) {
            checkExistCompany(myProject);
            myProjectRepository.insert(myProject);
        }
    }

    @Override
    public void delete(Long id) {
        myProjectRepository.delete(id);
    }

    /**
     * 自动填充查询条件，查询自己所负责的,
     *
     * @param filterCondition
     * @param userId
     * @return Boolean 返回为false代表不能查询，传入有误
     * @create 2021/5/11 17:16
     */
    protected Boolean autoWiredFilter(FilterCondition filterCondition, Long userId) {
        filterCondition.setPrincipal(userId);
        Long orgId = getOrgId(userId);
        if (orgId != null) {
            filterCondition.setResponsibleDept(orgId);
            return true;
        } else {
            logger.info("找不到组织，userId:{}", userId);
            return false;
        }
    }

    /**
     * 根据用户id获得组织id
     *
     * @param userId
     * @return java.lang.Long
     * @create 2021/5/12 10:13
     */
    protected Long getOrgId(Long userId) {
        String orgIdStr = redisClient.get("Org:" + userId);
        if (!StringUtil.isEmpty(orgIdStr)) {
            return Long.parseLong(orgIdStr.split("-")[0]);
        } else {
            return null;
        }

    }

    protected List<MyProject> getProjectsByIds(String ids, FilterCondition filterCondition, List<String> status) {
        List<MyProject> myProjects;
        if (StringUtil.isEmpty(ids)) {
            //ids为空，导出按照条件筛选的全部
            myProjects = myProjectRepository.selectByCondition(filterCondition, status);
        } else {
            //不为空，按照id查询
            List<String> idList = Arrays.stream(ids.split(",")).collect(Collectors.toList());
            myProjects = myProjectRepository.selectByIdBatch(idList);
        }
        return myProjects;
    }

    /**
     * 将上传类转化为实体类
     *
     * @param baseExcelModels
     * @param userId
     * @param stationId
     * @return void
     * @create 2021/5/13 15:59
     */
    protected List<MyProject> convertUploadToDo(List<? extends BaseExcelModel> baseExcelModels, Long userId, Long stationId) {
        List<MyProject> myProjects = new ArrayList<>();
        for (BaseExcelModel baseExcelModel : baseExcelModels) {
            MyProject myProject = new MyProject();
            BeanUtils.copyProperties(baseExcelModel, myProject);
            if (baseExcelModel instanceof IntentionProjectUpload) {
                //意向项目导入考虑撞车情况
                checkExistCompany(myProject);
            }
            if (baseExcelModel instanceof SuccessProjectUpload) {
                //成功项目导入没有当前状态，需要对是否即将离场进行判断
                if (myProject.getExpireTime().getTime() - System.currentTimeMillis() > month) {
                    myProject.setCompanyStatus(MyProjectConsts.COMPANY_STATUS.Success.value());
                } else if (myProject.getExpireTime().getTime() - System.currentTimeMillis() <= month &&
                        myProject.getExpireTime().getTime() - System.currentTimeMillis() > 0) {
                    myProject.setCompanyStatus(MyProjectConsts.COMPANY_STATUS.LeaveSoon.value());
                } else {
                    logger.info("成功项目导入失败,离场时间:{}", myProject.getExpireTime());
                    continue;
                }
                setPrincipalByNameAndPhone(((SuccessProjectUpload) baseExcelModel).getPrincipalPhone(),
                        ((SuccessProjectUpload) baseExcelModel).getPrincipalTitle(),myProject, userId);
                setResponsibleDeptByName(((SuccessProjectUpload) baseExcelModel).getResponsibleDeptTitle(), myProject, stationId);
                //根据厂房名字查厂房
                setOfficeByName(((SuccessProjectUpload) baseExcelModel).getChosenOfficeTitle(),myProject,stationId);
            }
            if (baseExcelModel instanceof HistoryProjectUpload){
                setPrincipalByNameAndPhone(((HistoryProjectUpload) baseExcelModel).getPrincipalPhone(),
                        ((HistoryProjectUpload) baseExcelModel).getPrincipalTitle(),myProject, userId);
                setResponsibleDeptByName(((HistoryProjectUpload) baseExcelModel).getResponsibleDeptTitle(), myProject, stationId);
                setOfficeByName(((HistoryProjectUpload) baseExcelModel).getChosenOfficeTitle(),myProject,stationId);
            }
            autoWiredProjectByAdd(myProject, userId, stationId);
            myProjects.add(myProject);
        }
        return myProjects;
    }

    private void setOfficeByName(String chosenOfficeTitle, MyProject myProject, Long stationId) {
        if (!StringUtil.isEmpty(chosenOfficeTitle)) {
            ResponseEntity<ResultObject> responseEntity = authorityClient.findByStationIdAndOfficeTitle(stationId, chosenOfficeTitle);
            if (responseEntity != null) {
                if (responseEntity.getStatusCode().is2xxSuccessful()) {
                    Object results = responseEntity.getBody().getResults();
                    Office office = JSON.parseObject(JSON.toJSONString(results), Office.class);
                    if (office != null) {
                        myProject.setChosenOffice(office.getId());
                    } else {
                        logger.info("园区:{},没有名为:{}的厂房", stationId,chosenOfficeTitle);
                    }
                }
            }
        }
    }

    private void setResponsibleDeptByName(String deptTitle, MyProject myProject, Long stationId) {
        if (!StringUtil.isEmpty(deptTitle)) {
            ResponseEntity<ResultObject> responseEntity = authorityClient.searchOrgByStationId(stationId, null);
            if (responseEntity.getStatusCode().is2xxSuccessful()) {
                Object results = responseEntity.getBody().getResults();
                List<Organization> organizations = JSON.parseArray(JSON.toJSONString(results), Organization.class);
                if (CollectionUtil.isNotEmpty(organizations)) {
                    List<Organization> collect = organizations.stream()
                            .filter(r -> deptTitle.equals(r.getTitle()))
                            .collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(collect)) {
                        //取第一个
                        myProject.setResponsibleDept(collect.get(0).getId());
                    } else {
                        logger.info("找不到组织名为:{}的组织", deptTitle);
                    }
                }
            }
        }
    }

    private void setPrincipalByNameAndPhone(String phone , String name , MyProject myProject, Long userId) {
        if (StringUtil.isEmpty(phone) && StringUtil.isEmpty(name)) {
            logger.info("导入失败,没有负责人");
        } else if (!StringUtil.isEmpty(phone)) {
            //通过电话号码查找业务员
            ResponseEntity<ResultObject> responseEntity = authorityClient.getUserByPhone(phone);
            if (responseEntity != null) {
                if (responseEntity.getStatusCode().is2xxSuccessful()) {
                    Object results = responseEntity.getBody().getResults();
                    User user = JSON.parseObject(JSON.toJSONString(results), User.class);
                    if (user != null) {
                        myProject.setPrincipal(user.getId());
                    }
                }
            }
        } else {
            //遍历组织下的所有业务员
            ResponseEntity<ResultObject> responseEntity = authorityClient.getUserByOrgAndRoleName(getOrgId(userId), "salesman", null, null);
            if (responseEntity != null) {
                if (responseEntity.getStatusCode().is2xxSuccessful()) {
                    Object results = responseEntity.getBody().getResults();
                    List<UserProjectOrg> salesMans = JSON.parseArray(JSON.toJSONString(results), UserProjectOrg.class);
                    if (CollectionUtil.isNotEmpty(salesMans)) {
                        List<UserProjectOrg> collect = salesMans.stream()
                                .filter(s -> !name.equals(s.getUserTitle()))
                                .collect(Collectors.toList());
                        if (CollectionUtil.isNotEmpty(collect)) {
                            //取第一个
                            myProject.setPrincipal(collect.get(0).getUserId());
                        } else {
                            logger.info("找不到名为:{}的业务员", name);
                        }
                    }
                }
            } else {
                logger.info("当前部门没有业务员,orgId:{}", getOrgId(userId));
            }
        }
    }

    /**
     * 查询当前登录人的组织以及子组织
     * @param userId
     */
    private List<Organization> subOrg(Long userId) {
        String orgIdStr = redisClient.get("Org:" + userId);
        List<Organization> organizations = new ArrayList<>();
        //获取当前登录人的组织
        if(!StringUtil.isEmpty(orgIdStr)){
            //查询当前组织以及子组织信息
            ResponseEntity<ResultObject> responseEntity = authorityClient.getSubOrg(orgIdStr);
            if(responseEntity != null){
                if(responseEntity.getStatusCode().is2xxSuccessful()){
                    Object results = responseEntity.getBody().getResults();
                    organizations = JSON.parseArray(JSON.toJSONString(results),Organization.class);
                }
            }
        }
        return organizations;
    }
}
